﻿using NLog;
using System;
using System.Linq;
using System.Web;
using StructureMap;
using Enyim.Caching;
using Ayatta.Contract;
using System.Web.Mvc;
using System.Web.Security;
using System.Security.Principal;
using Ayatta.Common.Extension;
using Web.Core.BootstrapperTask;

namespace Web.Core
{
    /// <summary>
    /// 继承httpApplication,web应用程序入口
    /// </summary>
    public abstract class Application : HttpApplication
    {
        //protected static readonly Container Container = new Container();

        private static IContainer container;
        public static IContainer Container
        {
            get { return container ?? (container = new Container()); }
        }

        private static Logger logger;
        public static Logger Logger
        {
            get { return logger ?? (logger = NLog.LogManager.GetLogger("log")); }
        }

        protected Application()
        {
            AuthorizeRequest += (sender, e) =>
            {
                {
                    var identity = Context.User.Identity as FormsIdentity;
                    if (identity == null || !identity.IsAuthenticated) return;
                    Context.User = new GenericPrincipal(identity, new string[0]);
                }
            };
        }

        protected virtual void ApplicationSetup()
        {
            RegisterDependency();
            SetResolver();
            RunTask();
        }

        protected virtual void RegisterDependency()
        {
            Container.Configure(o =>
            {
                o.For<IBootstrapperTask>().Add<RegisterDefaultRoute>();
                o.For<IBootstrapperTask>().Add<RegisterDefaultGlobalFilter>();
                o.For<Lazy<IInfrastructureService>>().Use(c => new Lazy<IInfrastructureService>(() => WcfChannelFactory.GetChannel<IInfrastructureService>("InfrastructureService")));
                o.For<Lazy<IPassportService>>().Use(c => new Lazy<IPassportService>(() => WcfChannelFactory.GetChannel<IPassportService>("PassportService")));
                o.For<Lazy<IAccountService>>().Use(c => new Lazy<IAccountService>(() => WcfChannelFactory.GetChannel<IAccountService>("AccountService")));
                o.For<Lazy<IStoreService>>().Use(c => new Lazy<IStoreService>(() => WcfChannelFactory.GetChannel<IStoreService>("StoreService")));
                o.For<Lazy<ITradeService>>().Use(c => new Lazy<ITradeService>(() => WcfChannelFactory.GetChannel<ITradeService>("TradeService")));
                o.For<Lazy<IPlayService>>().Use(c => new Lazy<IPlayService>(() => WcfChannelFactory.GetChannel<IPlayService>("PlayService")));
                o.For<Lazy<IMiscService>>().Use(c => new Lazy<IMiscService>(() => WcfChannelFactory.GetChannel<IMiscService>("MiscService")));
                o.For<Lazy<IExtraService>>().Use(c => new Lazy<IExtraService>(() => WcfChannelFactory.GetChannel<IExtraService>("ExtraService")));
                o.For<IMemcachedClient>().HybridHttpOrThreadLocalScoped().Use(new MemcachedClient());
            });
        }

        private static void RunTask()
        {
            var tasks = Container.GetAllInstances<IBootstrapperTask>();
            tasks.ForEach(o => o.Execute());
        }

        private static void SetResolver()
        {
            DependencyResolver.SetResolver(t => (t.IsClass && !t.IsAbstract) ? Container.GetInstance(t) : null, t => (t.IsClass && !t.IsAbstract) ? Container.GetAllInstances(t).OfType<object>() : new object[] { });
        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            ApplicationSetup();
        }

        protected void Application_End()
        {
            ApplicationTearDown();
            container = null;
            logger = null;
        }

        protected virtual void ApplicationTearDown()
        {

        }
    }
}